#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
搜狐号自动保存草稿程序 v2.0
新增功能：
1. 自动读取指定目录下的markdown文章
2. 解析markdown内容并转换为HTML
3. 自动保存为搜狐号草稿
4. 成功保存后将文章移动到已发目录
"""

import requests
import json
import time
import os
import shutil
import re
from pathlib import Path
from urllib.parse import urlencode
from typing import Dict, Any, Optional, List
import logging
import markdown
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('sohu_draft_v2.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class SohuDraftPublisherV2:
    """搜狐号草稿发布器 v2.0"""
    
    def __init__(self, config_file: str = 'sohu_config.json'):
        """初始化发布器
        
        Args:
            config_file: 配置文件路径
        """
        self.config = self._load_config(config_file)
        self.session = requests.Session()
        self._setup_session()
        
        # 初始化markdown转换器
        self.md = markdown.Markdown(extensions=['extra', 'codehilite'])
    
    def _load_config(self, config_file: str) -> Dict[str, Any]:
        """加载配置文件"""
        try:
            with open(config_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except FileNotFoundError:
            logger.error(f"配置文件 {config_file} 不存在")
            raise
        except json.JSONDecodeError:
            logger.error(f"配置文件 {config_file} 格式错误")
            raise
    
    def _setup_session(self):
        """设置请求会话"""
        headers = {
            'accept': '*/*',
            'accept-encoding': 'gzip, deflate, br, zstd',
            'accept-language': 'zh-CN,zh;q=0.9',
            'connection': 'keep-alive',
            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'host': 'mp.sohu.com',
            'origin': 'https://mp.sohu.com',
            'referer': 'https://mp.sohu.com/mpfe/v4/contentManagement/news/addarticle?contentStatus=1',
            'sec-ch-ua': '"Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"',
            'sec-ch-ua-mobile': '?0',
            'sec-ch-ua-platform': '"macOS"',
            'sec-fetch-dest': 'empty',
            'sec-fetch-mode': 'cors',
            'sec-fetch-site': 'same-origin',
            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
            'x-requested-with': 'XMLHttpRequest'
        }
        
        # 设置Cookie
        if 'cookie' in self.config:
            headers['cookie'] = self.config['cookie']
        
        self.session.headers.update(headers)
    
    def _extract_title_from_filename(self, filename: str) -> str:
        """从文件名提取标题"""
        # 移除.md扩展名
        title = filename.replace('.md', '')
        return title
    
    def _extract_brief_from_content(self, content: str, max_length: int = 100) -> str:
        """从内容中提取摘要"""
        # 移除markdown标记
        text = re.sub(r'[#*`\[\]()_~]', '', content)
        # 移除多余的空白字符
        text = re.sub(r'\s+', ' ', text).strip()
        
        # 提取前几句话作为摘要
        sentences = text.split('。')
        brief = ''
        for sentence in sentences:
            if len(brief + sentence + '。') <= max_length:
                brief += sentence + '。'
            else:
                break
        
        # 如果摘要太短，直接截取前max_length个字符
        if len(brief) < 20:
            brief = text[:max_length] + '...' if len(text) > max_length else text
        
        return brief
    
    def _markdown_to_html(self, markdown_content: str) -> str:
        """将markdown内容转换为HTML"""
        # 转换markdown为HTML
        html_content = self.md.convert(markdown_content)
        
        # 重置markdown转换器状态
        self.md.reset()
        
        return html_content
    
    def _read_markdown_file(self, file_path: str) -> Dict[str, str]:
        """读取markdown文件并解析内容"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 提取标题（从文件名）
            filename = os.path.basename(file_path)
            title = self._extract_title_from_filename(filename)
            
            # 提取摘要
            brief = self._extract_brief_from_content(content)
            
            # 转换为HTML
            html_content = self._markdown_to_html(content)
            
            return {
                'title': title,
                'brief': brief,
                'content': html_content,
                'original_file': file_path
            }
            
        except Exception as e:
            logger.error(f"读取文件 {file_path} 失败: {e}")
            return None
    
    def save_draft(self, title: str, brief: str, content: str, 
                   draft_id: Optional[str] = None) -> Dict[str, Any]:
        """保存草稿
        
        Args:
            title: 文章标题
            brief: 文章摘要
            content: 文章正文（HTML格式）
            draft_id: 草稿ID（可选，用于更新现有草稿）
        
        Returns:
            API响应结果
        """
        # 构建请求URL
        account_id = self.config.get('account_id', '121905676')
        url = f"https://mp.sohu.com/mpbp/bp/news/v4/news/draft?accountId={account_id}"
        
        # 构建表单数据
        form_data = {
            'title': title,
            'brief': brief,
            'content': content,
            'channelId': self.config.get('channel_id', 31),
            'categoryId': self.config.get('category_id', -1),
            'userColumnId': self.config.get('user_column_id', 0),
            'columnNewsIds': self.config.get('column_news_ids', ''),
            'businessCode': self.config.get('business_code', 0),
            'isOriginal': self.config.get('is_original', False),
            'cover': self.config.get('cover', ''),
            'attrIds': self.config.get('attr_ids', ''),
            'topicIds': self.config.get('topic_ids', ''),
            'userLabels': json.dumps(self.config.get('user_labels', []), ensure_ascii=False),
            'isAd': self.config.get('is_ad', 0),
            'reprint': self.config.get('reprint', False),
            'customTags': self.config.get('custom_tags', ''),
            'infoResource': self.config.get('info_resource', 0),
            'sourceUrl': self.config.get('source_url', ''),
            'visibleToLoginedUsers': self.config.get('visible_to_logined_users', 0),
            'accountId': account_id
        }
        
        # 如果提供了草稿ID，添加到表单数据中
        if draft_id:
            form_data['id'] = draft_id
        
        try:
            logger.info(f"开始保存草稿: {title}")
            
            # 发送POST请求
            response = self.session.post(url, data=form_data, timeout=30)
            response.raise_for_status()
            
            # 解析响应
            result = response.json()
            
            if result.get('status') == 'success' or response.status_code == 200:
                logger.info(f"草稿保存成功: {title}")
                return {
                    'success': True,
                    'message': '草稿保存成功',
                    'data': result
                }
            else:
                logger.error(f"草稿保存失败: {result}")
                return {
                    'success': False,
                    'message': f"草稿保存失败: {result.get('message', '未知错误')}",
                    'data': result
                }
                
        except requests.exceptions.RequestException as e:
            logger.error(f"网络请求错误: {e}")
            return {
                'success': False,
                'message': f"网络请求错误: {e}",
                'data': None
            }
        except json.JSONDecodeError as e:
            logger.error(f"响应解析错误: {e}")
            return {
                'success': False,
                'message': f"响应解析错误: {e}",
                'data': None
            }
        except Exception as e:
            logger.error(f"未知错误: {e}")
            return {
                'success': False,
                'message': f"未知错误: {e}",
                'data': None
            }
    
    def move_file_to_published(self, source_file: str, published_dir: str) -> bool:
        """将文件移动到已发目录
        
        Args:
            source_file: 源文件路径
            published_dir: 已发目录路径
        
        Returns:
            是否移动成功
        """
        try:
            # 确保已发目录存在
            os.makedirs(published_dir, exist_ok=True)
            
            # 构建目标文件路径
            filename = os.path.basename(source_file)
            target_file = os.path.join(published_dir, filename)
            
            # 如果目标文件已存在，添加时间戳
            if os.path.exists(target_file):
                name, ext = os.path.splitext(filename)
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                filename = f"{name}_{timestamp}{ext}"
                target_file = os.path.join(published_dir, filename)
            
            # 移动文件
            shutil.move(source_file, target_file)
            logger.info(f"文件已移动: {source_file} -> {target_file}")
            return True
            
        except Exception as e:
            logger.error(f"移动文件失败: {source_file} -> {published_dir}, 错误: {e}")
            return False
    
    def process_markdown_directory(self, markdown_dir: str, published_dir: str, 
                                 delay: int = 3) -> List[Dict[str, Any]]:
        """处理markdown目录下的所有文件
        
        Args:
            markdown_dir: markdown文件目录
            published_dir: 已发目录
            delay: 请求间隔时间（秒）
        
        Returns:
            处理结果列表
        """
        results = []
        
        # 获取所有markdown文件
        markdown_files = []
        for file in os.listdir(markdown_dir):
            if file.endswith('.md'):
                file_path = os.path.join(markdown_dir, file)
                if os.path.isfile(file_path):
                    markdown_files.append(file_path)
        
        if not markdown_files:
            logger.info(f"目录 {markdown_dir} 中没有找到markdown文件")
            return results
        
        logger.info(f"找到 {len(markdown_files)} 个markdown文件")
        
        # 处理每个文件
        for i, file_path in enumerate(markdown_files, 1):
            logger.info(f"处理第 {i}/{len(markdown_files)} 个文件: {os.path.basename(file_path)}")
            
            # 读取并解析markdown文件
            article_data = self._read_markdown_file(file_path)
            if not article_data:
                results.append({
                    'index': i,
                    'file': file_path,
                    'success': False,
                    'message': '文件读取失败',
                    'moved': False
                })
                continue
            
            # 保存草稿
            save_result = self.save_draft(
                title=article_data['title'],
                brief=article_data['brief'],
                content=article_data['content']
            )
            
            # 如果保存成功，移动文件
            moved = False
            if save_result['success']:
                moved = self.move_file_to_published(file_path, published_dir)
            
            results.append({
                'index': i,
                'file': file_path,
                'title': article_data['title'],
                'success': save_result['success'],
                'message': save_result['message'],
                'moved': moved,
                'save_result': save_result
            })
            
            # 添加延迟，避免请求过于频繁
            if i < len(markdown_files):
                time.sleep(delay)
        
        return results
    
    def generate_report(self, results: List[Dict[str, Any]]) -> str:
        """生成处理报告"""
        total = len(results)
        success_count = sum(1 for r in results if r['success'])
        moved_count = sum(1 for r in results if r.get('moved', False))
        
        report = f"""
=== 搜狐号草稿发布报告 v2.0 ===
处理时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
总文件数: {total}
成功保存: {success_count}
成功移动: {moved_count}
失败数量: {total - success_count}

详细结果:
"""
        
        for result in results:
            status = "✅ 成功" if result['success'] else "❌ 失败"
            moved_status = "✅ 已移动" if result.get('moved', False) else "❌ 未移动"
            filename = os.path.basename(result['file'])
            
            report += f"{result['index']:2d}. {filename}\n"
            report += f"    保存状态: {status}\n"
            report += f"    移动状态: {moved_status}\n"
            report += f"    消息: {result['message']}\n\n"
        
        return report

def main():
    """主函数"""
    try:
        # 创建发布器实例
        publisher = SohuDraftPublisherV2()
        
        # 配置目录路径
        markdown_dir = "/Users/fuzhengliang/Desktop/project-source/workspace-mygitee/zimeiti/星座"
        published_dir = "/Users/fuzhengliang/Desktop/project-source/workspace-mygitee/zimeiti/星座/已发"
        
        # 处理markdown文件
        logger.info("开始处理markdown文件...")
        results = publisher.process_markdown_directory(markdown_dir, published_dir)
        
        # 生成并显示报告
        report = publisher.generate_report(results)
        print(report)
        
        # 保存报告到文件
        report_file = f"sohu_publish_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
        with open(report_file, 'w', encoding='utf-8') as f:
            f.write(report)
        
        logger.info(f"处理完成，报告已保存到: {report_file}")
        
    except Exception as e:
        logger.error(f"程序执行错误: {e}")

if __name__ == '__main__':
    main()